package com.linln.modules.ticket.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.linln.common.enums.ServiceTypeEnum;
import com.linln.common.enums.TicketEnum;
import com.linln.modules.activityticket.domain.ActivityTicket;
import com.linln.modules.activityticket.service.ActivityTicketService;
import com.linln.modules.receiverecord.domain.ReceiveRecord;
import com.linln.modules.receiverecord.service.ReceiveRecordService;
import com.linln.modules.shopsService.domain.Shops;
import com.linln.modules.ticket.rule.Rule;
import com.linln.modules.ticket.rule.RuleResult;
import com.linln.common.utils.CodeUtil;
import com.linln.common.utils.DateUtil;
import com.linln.common.utils.PathMappingUtil;
import com.linln.common.utils.UUIDUtil;
import com.linln.common.vo.JsonResult;
import com.linln.common.vo.PageResult;
import com.linln.modules.capital.service.ShopCapitalService;
import com.linln.modules.shopsService.repository.ShopsRepository;
import com.linln.modules.system.domain.User;
import com.linln.modules.system.service.UserService;
import com.linln.modules.ticket.domain.TicketCustomerOriginal;
import com.linln.modules.ticket.domain.TicketLog;
import com.linln.modules.ticket.service.TicketLogService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linln.modules.ticket.domain.Ticket;
import com.linln.modules.ticket.repository.TicketMapper;
import com.linln.modules.ticket.service.TicketService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.ParseException;
import java.util.*;

/**
 * @author : pengliang
 * @version V1.0
 * @Project: timo
 * @Package com.linln.modeles.ticket.service.impl
 * @Descriptio /**
 * @Project: timo
 * @Package com.linln.modeles.ticket.service.impl
 * @Description: TODO
 * @date Date : 2020年11月23日 13:43
 */
@Service
public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> implements TicketService {

    @Autowired
    @Qualifier("ticketMapper")
    private TicketMapper ticketMapper;
    @Autowired
    private TicketLogService ticketLogService;
    @Autowired
    private UserService userService;
    @Autowired
    private ShopsRepository shopsRepository;
    @Autowired
    private ShopCapitalService shopCapitalService;

    /**
     * 获取全部的服务券数量
     *
     * @param userId
     * @return
     */
//    @Cacheable(cacheNames = "ticket/allTicketCount")
    @Override
    public Integer getAllTicketCount(long userId) {
        return ticketMapper.getAllTicketCount(userId);
    }

    /**
     * 获取未使用的服务券
     *
     * @param userId
     * @return
     */
//    @Cacheable(cacheNames = "ticket/notUse")
    @Override
    public PageInfo<Ticket> getNotUseTicket(long userId, Integer pageNum, Integer limit) {
        startLimit(pageNum, limit);
        return new PageInfo<Ticket>(ticketMapper.getTicket(userId, TicketEnum.NOTUSE.getCode()));
    }

    //获取已使用的服务券
//    @Cacheable(cacheNames = "ticket/used")
    @Override
    public PageInfo<Ticket> getUsedTicket(long userId, Integer pageNum, Integer limit) {
        startLimit(pageNum, limit);
        return new PageInfo<Ticket>(ticketMapper.getTicket(userId, TicketEnum.USED.getCode()));
    }

    //获取已过期的服务券
//    @Cacheable(cacheNames = "ticket/expire")
    @Override
    public PageInfo<Ticket> getExpireTicket(long userId, Integer pageNum, Integer limit) {
        startLimit(pageNum, limit);
        return new PageInfo<Ticket>(ticketMapper.getTicket(userId, TicketEnum.EXPIRE.getCode()));
    }

    //    @CacheEvict(cacheNames = {"ticket/used","ticket/notUse","ticket/allTicketCount"}, allEntries = true)
    @Override
    public boolean addTicket(Ticket ticket) {
        return save(ticket);
    }

    //获取服务券详情信息
//    @Cacheable("ticketInfo")
    @Override
    public Ticket getTicketInfo(String ticketId) {
        return ticketMapper.getTicketInfo(ticketId, null);
    }

    @Autowired
    @Qualifier("compositeRule")
    private Rule rule;

//    //通过券码核销
//    @Override
//    @Transactional
//    @CacheEvict(cacheNames = {"ticket/used", "ticket/notUse", "ticketInfo", "VerificationRecord"}, allEntries = true)
//    public JsonResult ticketCodeVerification(long userId, String ticketCode, String car, String imgPath) throws ParseException {
//        Ticket ticket = ticketMapper.getTicketInfo(null, ticketCode);
//        RuleResult ruleResult = null;
//        if (rule.support(ticket.getUseRuleId())) {
//            ruleResult = rule.handlerCode(String.valueOf(userId), ticket);
//        }
//        if (ruleResult == null || ruleResult.getResult()) {
//            return verification(ticket, userId, car, imgPath);
//        } else {
//            return JsonResult.error(ruleResult.getMsg());
//        }
//    }

    @Override
    @Transactional
//    @CacheEvict(cacheNames = {"ticket/used", "ticket/notUse", "ticketInfo", "VerificationRecord"}, allEntries = true)
    public JsonResult ticketCodeVerification(long userId, String ticketCode, String car, String imgPath, String shopId) throws ParseException {
        Ticket ticket = ticketMapper.getTicketInfo(null, ticketCode);
        RuleResult ruleResult = null;
        if (rule.support(ticket.getUseRuleId())) {
            ruleResult = rule.handlerCode(String.valueOf(userId), ticket, shopId);
        }
        if (ruleResult == null || ruleResult.getResult()) {
            return verification(ticket, userId, car, imgPath, shopId);
        } else {
            return JsonResult.error(ruleResult.getMsg());
        }
    }

    //核销方法
    @Transactional
    public JsonResult verification(Ticket ticket, long userId, String car, String imgPath, String shopId) {
        //通过当前用户id 查询所对应的店铺
//        String shopsId = shopsRepository.byUsersearchShopId(userId);
        Shops shops = shopsRepository.getOne(shopId);
        List<String> shopTypes = Arrays.asList(shops.getShopType().split(","));
        if(!shopTypes.contains(ticket.getServiceTypeId())){
            return JsonResult.error("该店铺不支持核销此服务券");
        }
        if(ticket.getStartDate()==null){
            ticket.setStartDate(DateUtil.formatDate(new Date(), "yyyy-MM-dd"));
        }
        if (ticket == null) {
            return JsonResult.error("优惠券有误，请重试");
        } else if (Strings.isBlank(shopId)) {
            return JsonResult.error("您不是店铺人员");
        } else if (TicketEnum.USED.getCode().equals(ticket.getStatus())) {
            return JsonResult.error("该券已被使用");
        } else if (DateUtil.compareToDate(new Date(), DateUtil.parseDate(ticket.getStartDate(), "yyyy-MM-dd")) <= 0) {
            return JsonResult.error("该券未到使用时间");
        } else if (TicketEnum.EXPIRE.getCode().equals(ticket.getStatus())) {
            return JsonResult.error("该券已经过期");
        } else if (new Date().after(Objects.requireNonNull(DateUtil.parseDate(ticket.getExpirDate(), "yyyy-MM-dd")))) {
            return JsonResult.error("该券已经过期");
        } else if (ServiceTypeEnum.YEARRWVIEW.equals(ticket.getServiceTypeId())) {
            return JsonResult.error("年审券不能核销");
        }
        //创建核销记录对象
        TicketLog ticketLog = createTicketLog(ticket, String.valueOf(userId), shopId, car, imgPath);
//        PathMappingUtil.saveImg(PathMappingUtil.VERIFICATIONPATH, PathMappingUtil.VERIFICATIONPATHMAPPING, file);
        //将服务券改为已使用                                                                     //保存核销记录
        if (ticketMapper.updateTicketStatus(ticket.getTicketId(), TicketEnum.USED.getCode()) && ticketLogService.addTicketLog(ticketLog)) {
            //修改店铺资金
            shopCapitalService.addShopCapitalMoney(shopId, ticketLog.getVerificationMoney());
            return JsonResult.ok("核销成功");
        } else {
            return JsonResult.error("核销失败");
        }
    }

    //    //通过id核销
//    @Transactional
//    @Override
//    public JsonResult ticketIdVerification(long userId, String ticketId) throws ParseException {
//        Ticket ticket = ticketMapper.getTicketInfo(ticketId, null);
//        RuleResult ruleResult = null;
//        if (rule.support(ticket.getRulesUseName())) {
//            ruleResult = rule.handlerId(String.valueOf(userId), ticketId);
//        }
//        if (ruleResult != null && ruleResult.getResult()) {
//            return verification(ticket, userId, null);
//        } else {
//            return JsonResult.error(ruleResult.getMsg());
//        }
//    }

//    //核销方法
//    @Transactional
//    public JsonResult verification(Ticket ticket, long userId, String car, String imgPath) {
//        //通过当前用户id 查询所对应的店铺
//        String shopsId = shopsRepository.byUsersearchShopId(userId);
//        if (ticket == null) {
//            return JsonResult.error("优惠券有误，请重试");
//        } else if (Strings.isBlank(shopsId)) {
//            return JsonResult.error("您不是店铺人员");
//        } else if (TicketEnum.USED.getCode().equals(ticket.getStatus())) {
//            return JsonResult.error("该券已被使用");
//        } else if (TicketEnum.EXPIRE.getCode().equals(ticket.getStatus())) {
//            return JsonResult.error("该券已经过期");
//        } else if (new Date().after(Objects.requireNonNull(DateUtil.parseDate(ticket.getExpirDate(), "yyyy-MM-dd")))) {
//            return JsonResult.error("该券已经过期");
//        }
//        //创建核销记录对象
//        TicketLog ticketLog = createTicketLog(ticket, String.valueOf(userId), shopsId, car, imgPath);
////        PathMappingUtil.saveImg(PathMappingUtil.VERIFICATIONPATH, PathMappingUtil.VERIFICATIONPATHMAPPING, file);
//        //将服务券改为已使用                                                                     //保存核销记录
//        if (ticketMapper.updateTicketStatus(ticket.getTicketId(), TicketEnum.USED.getCode()) && ticketLogService.addTicketLog(ticketLog)) {
//            //修改店铺资金
//            shopCapitalService.addShopCapitalMoney(shopsId, ticketLog.getVerificationMoney());
//            return JsonResult.ok("核销成功");
//        } else {
//            return JsonResult.error("核销失败");
//        }
//    }

    @Override
    public Map<String, Object> saveVerificationImg(MultipartFile file) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            String imgPath = PathMappingUtil.saveImg(PathMappingUtil.VERIFICATIONPATH, PathMappingUtil.VERIFICATIONPATHMAPPING, file);
            map.put("code", 200);
            map.put("msg", "保存核销图片成功");
            map.put("data", new HashMap<String, Object>() {{
                put("imgPath", imgPath);
            }});
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        map.put("code", 200);
        map.put("msg", "保存核销图片失败");
        return map;
    }

    @Value("${server.ip}")
    String ip;

    @Override
    public Map<String, Object> saveVerificationImgByBase64(String base64) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            String imgPath = PathMappingUtil.saveImg(PathMappingUtil.VERIFICATIONPATH, PathMappingUtil.VERIFICATIONPATHMAPPING, PathMappingUtil.base64ToMultipart(base64));
            map.put("code", 200);
            map.put("msg", "保存图片成功");
            map.put("data", new HashMap<String, Object>() {{
                put("imgPath", ip + imgPath);
            }});
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        map.put("code", 200);
        map.put("msg", "保存图片失败");
        return map;
    }

    private TicketLog createTicketLog(Ticket ticket, String userId, String shopsId, String car, String picture) {
        TicketLog ticketLog = new TicketLog();
        //设置核销人员id
        ticketLog.setOperUserId(userId);
        //店铺id
        ticketLog.setShopId(shopsId);
        //服务券id
        ticketLog.setTicketId(ticket.getTicketId());
        //核销时间 当前时间
        ticketLog.setVerificationDate(new Date());
        //车牌
        ticketLog.setLicensePlate(car);
        //核销图片地址
        ticketLog.setVerificationPicture(picture);
        //核销金额
        ticketLog.setVerificationMoney(ticket.getTicketMoney());
        //核销积分
        ticketLog.setVerificationIntegral(ticket.getTicketIntegral());
        return ticketLog;
    }


    @Override
    public Map<String, Object> getVerificationRecord(long userId, Integer pageNum, Integer limit, String date, String shopId) {
//        String shopId = shopsRepository.byUsersearchShopId(userId);
        return getVerificationRecordByShopId(shopId, pageNum, limit, date);
    }

    //    @Cacheable("VerificationRecord")
    //**通过店铺id 查询这家店铺的核销历史
    public Map<String, Object> getVerificationRecordByShopId(String shopId, Integer pageNum, Integer limit, String date) {
        startLimit(pageNum, limit);
        Map<String, Object> map = new HashMap<>();
        if (Strings.isBlank(date)) {
            date = DateUtil.formatDate(new Date(), "yyyy-MM-dd");
        }
//        String formatDate = DateUtil.formatDate(new Date(), "yyyy-MM-dd");
        PageInfo<TicketLog> pageInfo = new PageInfo<TicketLog>(ticketMapper.getVerificationRecord(shopId, date));
        map.put("data", pageInfo.getList());
        map.put("monthCount", ticketLogService.getSameMonthVerificationCount(shopId, date));
        map.put("total", pageInfo.getTotal());
        return map;
    }

    /**
     * 开启分页
     *
     * @param pageNum
     * @param limit
     */
    private void startLimit(Integer pageNum, Integer limit) {
        PageHelper.startPage(pageNum + 1, limit);
    }


//    @Override
//    public boolean addBatch(List<Ticket> ticketList) {
//        return ticketMapper.insertBatch(ticketList);
//    }

    @Override
    public boolean checkExpire() {
        return ticketMapper.checkExpire();
    }

    @Transactional
    @Override
    public Map<String, Object> registerUserAndSendTicket(User user) {
        Map<String, Object> map = null;
        user = userService.save(user);
        TicketCustomerOriginal ticketCustomerOriginal = ticketMapper.selectTicketCustomerOriginalByUserPhone(user.getPhone());
        if (ticketCustomerOriginal != null) {
            //添加服务券
            List<Ticket> ticket = createTicket(user.getId(), ticketCustomerOriginal);
            map = new HashMap<>();
            map.put("count", ticketCustomerOriginal.getTicketCount());
            //批量添加服务券
            this.saveBatch(ticket);
        }

        return map;
    }


    /**
     * 创建服务券
     *
     * @param
     * @return
     */
    private List<Ticket> createTicket(Long userId, TicketCustomerOriginal ticketCustomerOriginal) {
        List<Ticket> list = new ArrayList<>();
        for (int i = 0; i < ticketCustomerOriginal.getTicketCount(); i++) {
            Ticket ticket = new Ticket();
            //服务券id
            ticket.setTicketId(UUIDUtil.randomUUID32());
            //设置券码
            ticket.setTicketCode(CodeUtil.trans(CodeUtil.createOne()));
            //用户id
            ticket.setUserId(userId);
            //服务券类型id
            ticket.setServiceTypeId(ticketCustomerOriginal.getTicketTypeId());
            //购买时间 为当前时间
            ticket.setBuyDate(DateUtil.formatDate(new Date()));
            //使用状态为未使用
            ticket.setStatus(TicketEnum.NOTUSE.getCode());
            //1月 = 2592000000  毫秒  过期时间为下一个月
            ticket.setExpirDate(DateUtil.formatDate(new Date(System.currentTimeMillis() + 2592000000L), "yyyy-MM-dd"));
            //使用详情
            ticket.setExplain("每张仅限一人使用；每月仅限使用1张");
            //获取渠道  0赠送
            ticket.setObtain(0L);
            //使用规则  自然月
            ticket.setUseRuleId("66555266364e430d960e90961171cf2a");
            //服务券金额 为
            ticket.setTicketMoney(ticketCustomerOriginal.getCostMoney());
            //服务券积分为0
            ticket.setTicketIntegral(0);
            list.add(ticket);
        }
//        return ticketService.addBatch(list);
        return list;
    }


    @Override
    public PageResult<TicketLog> getTicketLogList(Integer pageNum, Integer limit, String shopId, String startDate, String endDate) {
        PageHelper.startPage(pageNum, limit);
        PageInfo<TicketLog> pageInfo = new PageInfo<>(ticketMapper.getTicketLogList(shopId, startDate, endDate));
        PageResult<TicketLog> pageResult = new PageResult();
        pageResult.setData(pageInfo.getList());
        pageResult.setCount(pageInfo.getTotal());
        pageResult.setCode(0);
        return pageResult;
    }

    @Autowired
    private ActivityTicketService activityTicketService;

    @Autowired
    private ReceiveRecordService receiveRecordService;

    //通过活动券赠送用户优惠券 userId 用户id
    @Override
    @Transactional
    public Map<String, Object> giveCanGiveActivity(long userId) {
        Map<String, Object> map = new HashMap<>();
        Map<String, ReceiveRecord> grantTicketList = receiveRecordService.getGrantTicketList(userId);
        List<ActivityTicket> canGiveActivity = activityTicketService.getCanGiveActivity();
        canGiveActivity.forEach(item -> {
            if (judgeUserCanNotGet(item, userId)) {
                //判断这个用户是否已经领取过优惠券
                if (grantTicketList != null && !grantTicketList.containsKey(item.getAtId()+":"+userId)) {
                    //这个用户没有领取过 赠送
                    //添加优惠券
                    addTicket(createTicket(userService.getById(userId), item));
                    ReceiveRecord receiveRecord = new ReceiveRecord();
                    //领取时间
                    receiveRecord.setReceiveDate(DateUtil.formatDate(new Date()));
                    //活动券id
                    receiveRecord.setAtId(item.getAtId());
                    //用户id
                    receiveRecord.setUserId(userId);
                    //添加领取记录
                    receiveRecordService.addReceiveRecord(receiveRecord);
                    //修改活动券数量
                    int count = activityTicketService.buyIntegralService(item.getAtId());
                    map.merge("count", count, (a, b) -> (int) a + (int) b);
                }
            }
        });
        return map;
    }


    private Ticket createTicket(User user, ActivityTicket activityTicket) {
        Date date = new Date();
        String currentDate = DateUtil.formatDate(date);
        Ticket ticket = new Ticket();
        //券码
        ticket.setTicketCode(CodeUtil.trans(CodeUtil.createOne()));
        //购买日期
        ticket.setBuyDate(currentDate);
        //状态 未使用
        ticket.setStatus(TicketEnum.NOTUSE.getCode());
        //过期时间 当前时间+活动券指定的时间
        if (activityTicket.getAtValidDay() != null) {
            ticket.setExpirDate(DateUtil.formatDate(DateUtil.getAppointDate(date, activityTicket.getAtValidDay()), "yyyy-MM-dd"));
        } else {
            ticket.setStartDate(activityTicket.getAtValidStartDate());
            ticket.setExpirDate(activityTicket.getAtValidEndDate());
        }
        //券 说明   活动券的说明
        ticket.setExplain(activityTicket.getAtExplain());
        //券类型  活动券类型
        ticket.setServiceTypeId(activityTicket.getStId());
        //使用规则id
        ticket.setUseRuleId(activityTicket.getAtUseRuleId());
        //积分
        ticket.setTicketIntegral(activityTicket.getAtIntegral());
        //金额
        ticket.setTicketMoney(activityTicket.getAtMoney());
        //用户id
        ticket.setUserId(user.getId());
        return ticket;
    }

    //判断这个用户能否得到这张券
    private boolean judgeUserCanNotGet(ActivityTicket activityTicket, long userId) {
        if (activityTicket.getAtUserType() != null) {
            boolean flag = false;
            switch (activityTicket.getAtUserType()) {
                case 1: {
                    //所有用户
                    flag = true;
                    break;
                }
                case 2: {
                    //新用户
                    User user = userService.getById(userId);
                    if (DateUtil.compareToDate(DateUtil.getAppointDate(user.getCreateDate(), 1), new Date()) == 1) {
                        flag = true;
                    }
                    break;
                }
                case 3: case 4: {
                    //指定用户
                    String userPhones = activityTicket.getAtUserPhones();
                    List<String> list = Arrays.asList(userPhones.split(","));
                    User user = userService.getById(userId);
                    if (list.contains(user.getPhone())) {
                        flag = true;
                    }
                    break;
                }
            }
            return flag;
        }

        return false;
    }


}
